"use strict";

const Ws    = require("ws");
const PB    = require("protobufjs");
//const PBProtoIns = PB.loadProtoFile(__dirname + "/packet/Message.proto");
const PBProtoIns = PB.loadSync(__dirname + "/packet/Message.proto");
//const PBJsIns = require("./packet/Message.js");
const protocols = require("./api.json");

const type = protocols.PROTOCOL;
let PacketId = {};
let ClassId = {};

(function(){
  for(let k in protocols) {
    if (protocols.hasOwnProperty(k) && typeof protocols[k] == "number") {
      PacketId[protocols[k]] = k.replace(/^TO_|^ON_/,"").toLowerCase().replace(/_(\S)/g,(all, letter)=>{return letter.toUpperCase()});;
      ClassId[protocols[k]] = PacketId[protocols[k]].replace(/\b(\w)|\s(\w)/g, m => {return m.toUpperCase();});
    }
  }
})();

function DecodeData(message) {
  let msg = {};
  switch (type) {
    case "JSON":
      msg = JSON.parse(message);
    break;
    case "ProtoBuf":
      let sender = PBProtoIns.lookup("Message");
      msg = sender.decode(message);
    break;
    default: return {
        packetId: 0,
        value: {}
    }; break;
  }

  msg.value = msg[PacketId[msg.packetId]];

  return msg;
}

function EncodeData(message){
  if (!message || typeof message != "object") {return null;}
  message.timestamp = new Date().valueOf();

  let msg = {};
  switch (type) {
    case "JSON":
      msg = JSON.stringify(message);
    break;
    case "ProtoBuf":
      let sender = PBProtoIns.lookup("Message");
      msg = sender.encode(message).finish();
    break;
    default: break;
  }
  return msg;
}

Ws.prototype.SendPacket = function(packetId, message) {
    if (this.readyState === Ws.OPEN) {
        let msg = {};
        msg.packetId = packetId;
        msg[PacketId[packetId]] = message || {};

        let data = EncodeData(msg);
        
//        let Message = PBJsIns.require("proto.Message");
//        let sender = new Message();
//        sender.setPacketId(packetId);
//        sender["set" + ClassId[packetId]](message);
//        let data = sender.serializeBinary();

        this.send(data, function (err) {
            if (err) {Logger.error("Server Send Data To Client Return Error: ", err);}
        });
    } else {
        this.readyState = Ws.CLOSED;
        this.emit('close');
        this.removeAllListeners();
    }
}

module.exports = {
  "encode": EncodeData,
  "decode": DecodeData
};
